<?php declare(strict_types=1);

/**
 * @author      guosir
 * @copyright   2023-2025 owner
 **/

namespace Srv\Apps\Apis\User\Ctl;

use Srv\Apps\Apis\Admin\Ctl\AdminCtl;
use Srv\Apps\Apis\Common\Ctl\StorageCtl;
use Srv\Apps\Apis\Common\DefCtl\DefFeedbackCtl;
use Srv\Apps\Apis\Common\IdxCtl\IdxIp;
use Srv\Apps\Proto\DTO\User\FeedbackListDTO;
use Srv\Apps\Proto\Enum\Common\FeedbackStatusEnum;
use Srv\Apps\Proto\Enum\YesOrNoEnum;
use Srv\Apps\Proto\VO\Admin\AdmUserInfoBasicVO;
use Srv\Apps\Proto\VO\User\FeedbackListVO;
use Srv\Apps\Proto\VO\User\FeedbackMediaVO;
use Srv\Apps\Proto\VO\User\FeedbackVO;
use Srv\Apps\Proto\VO\User\UserInfoBasicVO;
use Srv\Libs\Common\CommArray;
use Srv\Libs\Common\CommJson;
use Srv\Libs\Common\CommTime;
use Srv\Libs\Frame\AuthData;
use Srv\Libs\Frame\ControllerAbstract;
use Srv\Libs\Frame\Page;
use Srv\Libs\Storage\DataMysql;

final class FeedbackCtl extends ControllerAbstract
{
    private ?DataMysql $DbAuto              = null;     // DB-Write

    /**
     * @return static
     * tag
     */
    final public static function tag():self
    {
        $thisObject                         = self::tagGet();
        if($thisObject instanceof self){
            $thisObject->DbAuto             = self::getDbAuto();
        }
        return $thisObject;
    }

    /**
     * @param Page $Page
     * @param array $whereData
     * @return FeedbackListVO|null
     * getFeedbackList
     */
    public function getFeedbackList(Page $Page, array $whereData):?FeedbackListVO
    {
        $limitString        = $Page->getLimitString();
        $whereString        = ' WHERE fdbr_delete=0 ';
        $whereInfoString    = ' WHERE usi_delete=0';
        $infoSearch         = false;
        // 检索条件
        if(count($whereData) > 0) foreach ($whereData as $key => $val){
            switch ($key){
                case FeedbackListDTO::_userId:
                    $whereString        .= (strlen($whereString)>0?' AND ':'').'user_id='. intval($val);
                    break;
                case FeedbackListDTO::_nickname:
                    $infoSearch         = true;
                    $whereInfoString    .= (strlen($whereInfoString)>0?' AND ':'').'usi_nickname LIKE \'%'.$this->DbAuto->getRealEscapeString($val).'%\'';
                    break;
                case FeedbackListDTO::_idNum:
                    if(strlen($val) > 10 && is_numeric($val)){
                        $whereString        .= (strlen($whereString)>0?' AND ':'').'user_id='. intval($val);
                    }else{
                        $infoSearch         = true;
                        $whereInfoString    .= (strlen($whereInfoString)>0?' AND ':'').'usi_idnum LIKE \'%'.$this->DbAuto->getRealEscapeString($val).'%\'';
                    }
                    break;
                case FeedbackListDTO::_admUserId:
                    $whereString        .= (strlen($whereString)>0?' AND ':'').'auir_id='. intval($val);
                    break;
                case FeedbackListDTO::_review:
                    $whereString        .= (strlen($whereString)>0?' AND ':'').'fdbr_review='. intval($val);
                    break;
                case FeedbackListDTO::_createTimeStart:
                    $whereString        .= (strlen($whereString)>0?' AND ':'').'fdbr_create_time>='. intval($val);
                    break;
                case FeedbackListDTO::_createTimeStop:
                    $whereString        .= (strlen($whereString)>0?' AND ':'').'fdbr_create_time<='. intval($val);
                    break;
            }
        }
        if($infoSearch){
            $subSql         = 'SELECT user_id FROM '.$this->DbAuto->getTableNameAll('user_info').$whereInfoString;
            $whereString    .=  (strlen($whereString)>0?' AND ':'').'user_id IN('.$subSql.')';
        }
        $isFail             = false;
        $sql                = 'SELECT SQL_CALC_FOUND_ROWS fdbr_id, fdbt_id, user_id, fdbr_ip, dup_id, fdbr_version, dcht_id, fdbr_content, fdbr_contact, fdbr_media_num, fdbr_media_list, fdbr_review, fdbr_review_time, auir_id, fdbr_review_remark, fdbr_create_time, fdbr_update_time FROM '.$this->DbAuto->getTableNameAll('feedback_record').$whereString.' ORDER BY fdbr_id DESC '.$limitString;
        $list               = $this->DbAuto->getData($sql, $isFail);
        $totalNum           = $this->DbAuto->getDataInt('SELECT FOUND_ROWS() as num', 'num');
        if($isFail) return null;
        $FeedbackVOList     = [];
        if(CommArray::isForeach($list)){
            $UserCtl                = UserCtl::tag();
            $userIdList             = array_unique(array_filter(array_map('intval', array_column($list, 'user_id'))));
            $admUserIdList          = array_unique(array_filter(array_map('intval', array_column($list, 'auir_id'))));
            $UserInfoBasicVOList    = $UserCtl->getUserInfoBasicBatch($userIdList);
            $AdmUserBasicVOList     = AdminCtl::tag()->getAdmUserInfoBasicBatch($admUserIdList);
            foreach($list as $item){
                $ultrIdItem         = intval($item['fdbr_id']??0);
                if($ultrIdItem < 1) continue;
                $userIdItem         = intval($item['user_id']);
                if($userIdItem < 1) continue;
                $FeedbackVO         = $this->getFeedbackVO($item);
                if(!($FeedbackVO instanceof FeedbackVO)) continue;
                $UserInfoBasicVO    = $UserInfoBasicVOList[$userIdItem]??null;
                if(!($UserInfoBasicVO instanceof UserInfoBasicVO)) continue;
                $FeedbackVO->setUserInfoBasic($UserInfoBasicVO);
                $admUserIdItem      = intval($item['auir_id']);
                $AdmUserInfoBasicVO = $AdmUserBasicVOList[$admUserIdItem]??null;
                if($AdmUserInfoBasicVO instanceof AdmUserInfoBasicVO) $FeedbackVO->setAdmUserBasic($AdmUserInfoBasicVO);
                $FeedbackVOList[]   = $FeedbackVO;
            }
        }
        $FeedbackListVO             = new FeedbackListVO();
        $FeedbackListVO->setList($FeedbackVOList);
        $FeedbackListVO->setPage($Page->getPageVO($totalNum));
        return $FeedbackListVO;
    }

    /**
     * @param array $info
     * @return FeedbackVO|null
     * getFeedbackVO
     */
    public function getFeedbackVO(array $info):?FeedbackVO{
        $ultrId             = intval($info['fdbr_id']??0);
        if($ultrId < 1) return null;
        $FeedbackVO         = new FeedbackVO();
        $FeedbackVO->setFdbrId($ultrId);
        $FeedbackVO->setUserId(intval($info['user_id']));
        $FeedbackVO->setFeedbackType(DefFeedbackCtl::tag()->getExtStrById(intval($info['fdbt_id']), DefFeedbackCtl::EXT_NAME));
        $FeedbackVO->setIpStr(IdxIp::tag()->getIpStrByInt(intval($info['fdbr_ip'])));
        $FeedbackVO->setVersion(trim($info['fdbr_version']));
        $FeedbackVO->setContent(trim($info['fdbr_content']));
        $FeedbackVO->setContact(trim($info['fdbr_contact']));
        $mediaNum           = intval($info['fdbr_media_num']);
        $FeedbackVO->setMediaNum($mediaNum);
        if($mediaNum > 0){
            $mediaListData  = CommJson::decodeArray($info['fdbr_media_list']);
            $mediaList      = [];
            if(isset($mediaListData['list']) && count($mediaListData['list']) > 0){
                $StorageCtl = StorageCtl::tag();
                foreach($mediaListData['list'] as $item){
                    if(!isset($item['type']) || !isset($item['url'])) continue;
                    $FeedbackMediaVO = new FeedbackMediaVO();
                    $FeedbackMediaVO->setType(intval($item['type']));
                    $FeedbackMediaVO->setUrl($StorageCtl->getStorageUrl($item['url'], true));
                    $mediaList[]     = $FeedbackMediaVO;
                }
            }
            if(count($mediaList)>0) $FeedbackVO->setMediaList($mediaList);
        }
        $FeedbackVO->setReview(FeedbackStatusEnum::parseValue($info['fdbr_review']));
        $FeedbackVO->setReviewTime(intval($info['fdbr_review_time']));
        $FeedbackVO->setReviewRemark(trim($info['fdbr_review_remark']));
        $FeedbackVO->setCreateTime(intval($info['fdbr_create_time']));
        $FeedbackVO->setUpdateTime(intval($info['fdbr_update_time']));
        return $FeedbackVO;
    }

    /**
     * @param array $fdbrIdList
     * @param int $review
     * @param string $reviewRemark
     * @return bool
     * setFeedbackReview
     */
    public function setFeedbackReview(array $fdbrIdList, int $review, string $reviewRemark):bool
    {
        if(count($fdbrIdList) < 1 || !in_array($review, [0, 1], true)) return false;
        $currTime           = CommTime::getTimeStamp();
        $admUserId          = AuthData::getLoginUserId();
        $setReview          = $review === YesOrNoEnum::YES_OR_NO_YES?FeedbackStatusEnum::Feedback_STATUS_ACCEPT:FeedbackStatusEnum::Feedback_STATUS_REJECT;
        $sql            = 'UPDATE '.$this->DbAuto->getTableNameAll('feedback_record').' SET fdbr_review='.$setReview.', fdbr_update_time='.$currTime.', fdbr_review_time='.$currTime.', auir_id='.$admUserId.', fdbr_review_remark=\''.$this->DbAuto->getRealEscapeString($reviewRemark).'\' WHERE fdbr_id IN('.implode(',', $fdbrIdList).') AND fdbr_review='.FeedbackStatusEnum::Feedback_STATUS_WAIT.' AND fdbr_delete=0';
        return $this->DbAuto->getDataNum($sql)>0;
    }

    /**
     * @param array $fdbrIdList
     * @return bool
     * checkReviewStatus
     */
    public function checkReviewStatus(array $fdbrIdList):bool
    {
        $fdbrIdListSize = count($fdbrIdList);
        if($fdbrIdListSize < 1) return false;
        $sql        = 'SELECT COUNT(fdbr_id) AS num FROM '.$this->DbAuto->getTableNameAll('feedback_record').' WHERE fdbr_id IN('.implode(',', $fdbrIdList).') AND fdbr_delete=0 AND fdbr_review='.FeedbackStatusEnum::Feedback_STATUS_WAIT;
        $num        = $this->DbAuto->getDataInt($sql, 'num');
        if($num !== $fdbrIdListSize) return false;
        return true;
    }
}